package cn.sdc.sfw.dao.types;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

public final class DbTypes {

	public final static DbType STRING = new DbTypeImpl(Types.VARCHAR,"string",false);
	public final static DbType SHORT = new DbTypeImpl(Types.SMALLINT,"short",true);
	public final static DbType INTEGER = new DbTypeImpl(Types.INTEGER,"integer",true);
	public final static DbType LONG = new DbTypeImpl(Types.BIGINT,"long",true);
	public final static DbType FLOAT = new DbTypeImpl(Types.FLOAT,"float",true);
	public final static DbType DOUBLE = new DbTypeImpl(Types.DOUBLE,"double",true);
	public final static DbType BIGDECIMAL = new DbTypeImpl(Types.DECIMAL,"bigDecimal",false);
	public final static DbType TIME = new DbTypeImpl(Types.TIME,"time",false);
	public final static DbType SQLDATE = new DbTypeImpl(Types.DATE,"date",false);
	public final static DbType TIMESTAMP = new DbTypeImpl(Types.TIMESTAMP,"timestamp",false);
	public final static DbType BINARY = new DbTypeImpl(Types.BINARY,"bytes",false);
	public final static DbType BOOLEAN = new DbTypeImpl(Types.BOOLEAN,"boolean",true);
	public final static DbType OBJECT = new DbTypeImpl(Types.VARCHAR,"object",false);

	private static final Class BYTE_ARRAY_CLASS = new byte[0].getClass(); 
	private static Map<Class, DbType> types_ = new HashMap<Class, DbType>();

	static {
		registerDbType(String.class, STRING);
		registerDbType(short.class, SHORT);
		registerDbType(Short.class, SHORT);
		registerDbType(int.class, INTEGER);
		registerDbType(Integer.class, INTEGER);
		registerDbType(long.class, LONG);
		registerDbType(Long.class, LONG);
		registerDbType(float.class, FLOAT);
		registerDbType(Float.class, FLOAT);
		registerDbType(double.class, DOUBLE);
		registerDbType(Double.class, DOUBLE);
		registerDbType(BigDecimal.class, BIGDECIMAL);
		registerDbType(java.sql.Date.class, SQLDATE);
		registerDbType(java.sql.Time.class, TIME);
		registerDbType(java.util.Date.class, TIMESTAMP);
		registerDbType(Timestamp.class, TIMESTAMP);
		registerDbType(Calendar.class, TIMESTAMP);
		registerDbType(BYTE_ARRAY_CLASS, BINARY);
		registerDbType(boolean.class, BOOLEAN);
		registerDbType(Boolean.class, BOOLEAN);
	}

	private DbTypes() {
	}
	
	public static void registerDbType(Class clazz, DbType DbType) {
		synchronized (types_) {
			types_.put(clazz, DbType);
		}
	}

	public static DbType getDbType(Object obj) {
		if (obj == null) {
			return OBJECT;
		}
		return getDbType(obj.getClass());
	}

	public static DbType getDbType(Class clazz) {
		if (clazz == null) {
			return OBJECT;
		}
		DbType DbType = (DbType)types_.get(clazz);
		if (DbType != null) {
			return DbType;
		}
		return OBJECT;
	}

	public static DbType getDbType(int type) {
		return getDbType(getJavaClass(type));
	}
	
	public static Class getJavaClass(int type) {
		switch (type) {
			case Types.TINYINT :
			case Types.SMALLINT :
				return Short.class;
			case Types.INTEGER :
				return Integer.class;
			case Types.BIGINT :
				return Long.class;
			case Types.REAL :
			case Types.FLOAT :
				return Float.class;
			case Types.DOUBLE :
				return Double.class;
			case Types.DECIMAL :
			case Types.NUMERIC :
				return BigDecimal.class;
			case Types.DATE :
				return Timestamp.class;
			case Types.TIME :
				return java.sql.Time.class;
			case Types.TIMESTAMP :
				return Timestamp.class;
			case Types.BINARY :
			case Types.VARBINARY :
			case Types.LONGVARBINARY :
				return BYTE_ARRAY_CLASS;
			case Types.CHAR :
			case Types.LONGVARCHAR :
			case Types.VARCHAR :
				return String.class;
			case Types.BOOLEAN :
				return Boolean.class;
			default :
				return null;
		}
	}
}
